#include "../include/ThreadManager.h"
#include "../include/LogSvr.h"
#include "../include/Singleton_T.h"

typedef Singleton_T<LogSvr> log;
static int count = 0;
THREAD_FUNC_RETURN_T func (void *arg)
{
    ThreadManager *thr_mgr = reinterpret_cast<ThreadManager*>(arg);
    int n = 0;
    if (count++ > 5) return 0;
    while (n++ < 2)
    {
	log::instance ()->put (LOG_RINFO, "thread %lu value = %d thr_count = %d\n", Thread::self (), n, thr_mgr->thr_count ());
    }
    ThreadManager::instance ()->spawn_n (1, func, ThreadManager::instance ());
    sleep(1);
    return 0;
}
thread_t cancel_thr_id;
void notify_cancel_thread (int )
{
    ThreadManager::instance ()->cancel (cancel_thr_id);
}
int grp_id = 0;
void notify_cancel_grp (int)
{
    log::instance ()->put (LOG_RINFO, "to cancel group %d\n", grp_id);
    ThreadManager::instance ()->cancel_grp (grp_id);
}
THREAD_FUNC_RETURN_T test_thread_cancel (void *)
{
    int i = 0;
    while (1)
    {
	if (ThreadManager::instance ()->testcancel (Thread::self ()) == 0)
	    break;
	//log::instance ()->put (LOG_RINFO, "test thread cancel n = %d\n");
	printf ("test thread cancel n = %d\n", i++);
    }
    //log::instance ()->put (LOG_RINFO, "test thread cancel success n = %d\n");
    printf ("test thread cancel success n = %d\n", i);
    return 0;
}
THREAD_FUNC_RETURN_T test_cancel_grp (void *)
{
    while (1)
    {
	sleep (1);
	if (ThreadManager::instance ()->testcancel (Thread::self ()) == 0)
	    break;
    }
    log::instance ()->put (LOG_RINFO, "grp %d is canceled\n", ThreadManager::instance ()->get_grp_id (Thread::self ()));
    return 0;
}
THREAD_FUNC_RETURN_T run_test (void *)
{
    log::instance ()->put (LOG_RINFO, "run test %lu\n", Thread::self ());
    sleep (2);
    return 0;
}
THREAD_FUNC_RETURN_T stable_test (void *)
{
    while (1)
    {
	sleep (1);
	log::instance ()->put (LOG_RINFO, "stable test %lu\n", Thread::self ());
	int grp_id = 0;
	if ((grp_id = ThreadManager::instance ()->spawn (stable_test)) != -1)
	{
	    log::instance ()->put (LOG_RINFO, "create a thread success, grp_id = %d\n", grp_id);
	}else
	    log::instance ()->put (LOG_RINFO, "create a thread failed\n");
	break;
    }
    return 0;
}
int main ()
{
    log::instance ()->open ("log");
    //signal (SIGINT, notify_cancel_thread);
    signal (SIGINT, notify_cancel_grp);
    /*
    int grp_id_1 = ThreadManager::instance ()->spawn_n (1, 
	    func, 
	    ThreadManager::instance ());
    int grp_id_2 = ThreadManager::instance ()->spawn (test_thread_cancel, 
	    0,
	    &cancel_thr_id);
	    */
#ifdef test_cancel
    int grp_id_3 = ThreadManager::instance ()->spawn_n (4, 
	    test_cancel_grp, 
	    ThreadManager::instance ());
    grp_id = grp_id_3;
    int grp_id_4 = ThreadManager::instance ()->spawn_n (4, 
	    test_cancel_grp, 
	    ThreadManager::instance ());
    sleep (2);
    ThreadManager::instance ()->cancel_grp (grp_id_4);
#endif
    //ThreadManager::instance ()->spawn (stable_test);
    ThreadManager::instance ()->spawn_n (30,
	    run_test);
    ThreadManager::instance ()->wait ();
    return 0;
}
